﻿using System;
using System.Collections.Generic;
using System.IO;
using PSE.Deployment.SetupBase.Configuration;
using PSE.Deployment.SetupBase.Parameter;
using PSE.Deployment.Engine.CustomExceptions;
using PSE.Deployment.Engine.Interfaces;
using System.Xml;

namespace PSE.Deployment.SetupBase.Steps
{
    public class UpdateWindowsRegistry : SetupStep<Configuration.Actions.UpdateWindowsRegistry>
    {
        private XmlDocument _documentParameter;

        public UpdateWindowsRegistry(IStepGroup parent, Group group, Configuration.Actions.UpdateWindowsRegistry action, Parameter.Enums.SetupMode setupMode)
            : base(parent, group, action, setupMode)
        {
            this.ResetProgress(Action.Keys.Count);

            _documentParameter = new XmlDocument();

            _documentParameter.LoadXml(PSE.Deployment.Util.Serializer.Serialize(SetupMainFactory.GetInstance().Parameter.GetType(), SetupMainFactory.GetInstance().Parameter));
        }

        public override void Execute()
        {
            this.ResetProgress(Action.Keys.Count);

            if (this.SetupMode == Parameter.Enums.SetupMode.Install)
            {
                CreateRegistries();
            }
            else if (this.SetupMode == Parameter.Enums.SetupMode.Uninstall)
            {
                UninstallArtefacts();
            }
        }

        public override void Undo()
        {
            if (this.SetupMode == Parameter.Enums.SetupMode.Install)
            {
                UninstallArtefacts();
            }
        }

        private void CreateRegistries()
        {
            foreach (RegistryKey registryKey in Action.Keys)
            {
                if (this.IsStopped())
                    break;

                try
                {
                    this.IncrementProgress(registryKey.Name);

                    Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(registryKey.Name);

                    foreach (RegistryValue registryValue in registryKey.Values)
                    {
                        if (this.IsStopped())
                            break;

                        if (!string.IsNullOrEmpty(registryValue.XPath))
                        {
                            registryValue.Value = GetParameterValue(registryValue.XPath);
                        }

                        key.SetValue(registryValue.Name, registryValue.Value, registryValue.RegistryValueKind);
                    }

                    this.AddUsedBy(registryKey.Name);
                }
                catch
                {
                    this.DecrementProgress(registryKey.Name);
                    throw;
                }
            }
        }

        protected override void UninstallArtefact(string artefactName)
        {
            if (Microsoft.Win32.Registry.LocalMachine.OpenSubKey(artefactName) != null)
                Microsoft.Win32.Registry.LocalMachine.DeleteSubKeyTree(artefactName);
        }

        private string GetParameterValue(string key)
        {
            XmlNode node = _documentParameter.SelectSingleNode(key);

            if (node != null)
            {
                return node.Value;
            }
            else
            {
                throw new Exception(string.Format("unable to locate the key '{0}' in the file parameters", key));
            }
        }
    }
}
